<template>
  <div class="code-display">
    <div class="code-header">

      <div class="actions">
        <el-tooltip content="复制全部" placement="top">
          <el-button type="primary" plain size="small" class="action-button" @click="copyCode">
            <el-icon>
              <DocumentCopy />
            </el-icon>
            <span>复制代码</span>
          </el-button>
        </el-tooltip>
        <el-tooltip content="全屏查看" placement="top">
          <el-button type="primary" plain size="small" class="action-button" @click="fullscreen = true">
            <el-icon>
              <FullScreen />
            </el-icon>
            <span>全屏</span>
          </el-button>
        </el-tooltip>
      </div>
    </div>

    <div class="code-content">
      <!-- 代码区域，使用预格式化文本 -->
      <div class="code-block">
        <div class="tabs-wrapper" v-if="codeFiles.length > 1">
          <div class="file-tabs">
            <div v-for="(file, index) in codeFiles" :key="index" class="file-tab"
              :class="{ 'active': activeFileIndex === index }" @click="activeFileIndex = index">
              <el-icon>
                <Document />
              </el-icon>
              <span class="file-name">{{ getFileName(file.name) }}</span>
            </div>
          </div>
        </div>

        <div class="code-content-wrapper">

          <div class="code-area">
            <pre><code v-html="highlightedCode" style="height: 1100px;"></code></pre>
          </div>
        </div>
      </div>
    </div>



    <!-- 全屏对话框 -->
    <el-dialog v-model="fullscreen" title="代码详情" width="90%" :fullscreen="isSmallScreen" destroy-on-close
      class="code-dialog">
      <div class="fullscreen-code">
        <div class="actions-bar">
          <div class="file-selection" v-if="codeFiles.length > 1">
            <el-select v-model="fullscreenFileIndex" placeholder="选择文件" class="file-select">
              <el-option v-for="(file, index) in codeFiles" :key="index" :label="file.name" :value="index" />
            </el-select>
          </div>
          <el-button type="primary" class="copy-button" @click="copyCurrentCode">
            <el-icon>
              <DocumentCopy />
            </el-icon>
            <span>复制当前文件</span>
          </el-button>
        </div>
        <div class="code-container">
          <div class="code-area fullscreen">
            <pre><code v-html="highlightedFullscreenCode"></code></pre>
          </div>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue';
import hljs from 'highlight.js';
import 'highlight.js/styles/atom-one-dark.css';
import { Notebook, DocumentCopy, FullScreen, Document } from '@element-plus/icons-vue';

// 接收的属性
const props = defineProps({
  code: {
    type: [Object, String],
    default: ''
  }
});

// 本地状态
const fullscreen = ref(false);
const showCopyNotification = ref(false);
const activeFileIndex = ref(0);
const fullscreenFileIndex = ref(0);

// 监听全屏状态变化，同步文件索引
watch(() => fullscreen.value, (isFullscreen) => {
  if (isFullscreen) {
    fullscreenFileIndex.value = activeFileIndex.value;
  }
});

// 监听文件索引变化，同步全屏索引
watch(() => activeFileIndex.value, (newIndex) => {
  if (fullscreen.value) {
    fullscreenFileIndex.value = newIndex;
  }
});

// 监听全屏文件索引变化，同步主索引
watch(() => fullscreenFileIndex.value, (newIndex) => {
  activeFileIndex.value = newIndex;
});

// 确保代码内容是字符串
const codeContent = computed(() => {
  if (typeof props.code === 'string') {
    return props.code;
  } else if (props.code && typeof props.code === 'object') {
    try {
      return JSON.stringify(props.code, null, 2);
    } catch (error) {
      console.error('代码对象序列化错误:', error);
      return '';
    }
  }
  return '';
});

// 解析代码文件
const codeFiles = computed(() => {
  const code = codeContent.value;
  if (!code) return [];

  // 解析代码块，识别文件分隔标记
  // 默认假设不同文件之间以 "// 文件：xxx" 或 "/* 文件：xxx */" 的形式分隔
  const filePattern = /\/\/\s*文件[:：](.+?)\s*\n|\/\*\s*文件[:：](.+?)\s*\*\/|\/\/\s*File[:：](.+?)\s*\n|\/\*\s*File[:：](.+?)\s*\*\//g;

  const parts = code.split(filePattern);
  if (parts.length <= 1) {
    // 没有找到明确的文件分隔符，尝试识别常见的文件注释
    const defaultFiles = detectFilesFromContent(code);
    if (defaultFiles.length > 0) {
      return defaultFiles;
    }

    // 如果没有明确的文件，则作为单个文件
    return [{ name: 'index.js', content: code }];
  }

  // 构建文件列表
  const files = [];
  for (let i = 1; i < parts.length; i += 5) { // 每5个部分为一组（4个匹配组+1个内容）
    const fileName = parts[i] || parts[i + 1] || parts[i + 2] || parts[i + 3] || 'unknown.js';
    const content = parts[i + 4] || '';
    if (content.trim()) {
      files.push({ name: fileName.trim(), content: content.trim() });
    }
  }

  return files.length > 0 ? files : [{ name: 'index.js', content: code }];
});

// 从内容中检测可能的文件
const detectFilesFromContent = (code) => {
  const files = [];

  // 常见文件指示注释模式
  const patterns = [
    // JS/TS 文件注释
    { regex: /\/\/\s*([\w.-]+\.(js|ts|jsx|tsx))\s*\n/g, group: 1 },
    // Vue 文件注释
    { regex: /\/\/\s*([\w.-]+\.vue)\s*\n/g, group: 1 },
    // HTML 文件注释
    { regex: /<!--\s*([\w.-]+\.html)\s*-->/g, group: 1 },
    // CSS 文件注释
    { regex: /\/\*\s*([\w.-]+\.css)\s*\*\//g, group: 1 },
    // App.js, index.js 等常见的文件名模式
    { regex: /\/\/\s*(App|index|main|server)\.(js|ts|jsx|tsx|vue)\s*\n/g, group: 0 }
  ];

  let currentContent = '';
  let lastIndex = 0;

  for (const pattern of patterns) {
    const regex = pattern.regex;
    regex.lastIndex = 0; // 重置正则表达式索引

    let match;
    while ((match = regex.exec(code)) !== null) {
      const fileName = match[pattern.group];
      const startIndex = match.index;

      // 添加前一个匹配到当前匹配之间的内容
      if (startIndex > lastIndex && currentContent) {
        files.push({
          name: files.length > 0 ? `unknown-${files.length}.js` : 'index.js',
          content: currentContent
        });
        currentContent = '';
      }

      // 查找下一个模式或文件结束
      const nextMatch = findNextFileStart(code, startIndex + match[0].length, patterns);
      const endIndex = nextMatch === -1 ? code.length : nextMatch;

      // 添加当前文件
      files.push({
        name: fileName,
        content: code.substring(startIndex + match[0].length, endIndex).trim()
      });

      lastIndex = endIndex;
    }
  }

  // 如果没有找到任何文件，作为单个文件返回
  if (files.length === 0 && code.trim()) {
    // 尝试从第一行注释猜测文件类型
    const firstLine = code.split('\n')[0];
    let fileName = 'index.js';

    if (firstLine.includes('.vue') || code.includes('<template>')) {
      fileName = 'App.vue';
    } else if (firstLine.includes('.jsx') || firstLine.includes('React')) {
      fileName = 'App.jsx';
    } else if (firstLine.includes('.ts')) {
      fileName = 'index.ts';
    } else if (firstLine.includes('.html') || code.includes('<!DOCTYPE')) {
      fileName = 'index.html';
    } else if (firstLine.includes('.css')) {
      fileName = 'styles.css';
    }

    files.push({ name: fileName, content: code });
  }

  return files;
};

// 查找下一个文件开始的位置
const findNextFileStart = (code, startIndex, patterns) => {
  const indices = [];

  for (const pattern of patterns) {
    const regex = new RegExp(pattern.regex.source, 'g');
    regex.lastIndex = startIndex;

    const match = regex.exec(code);
    if (match) {
      indices.push(match.index);
    }
  }

  return indices.length > 0 ? Math.min(...indices) : -1;
};

// 当前选择的文件
const currentFile = computed(() => {
  return codeFiles.value.length > activeFileIndex.value ? codeFiles.value[activeFileIndex.value] : null;
});

// 全屏模式下的文件
const fullscreenFile = computed(() => {
  return codeFiles.value.length > fullscreenFileIndex.value ? codeFiles.value[fullscreenFileIndex.value] : null;
});

// 获取文件名（不含路径）
const getFileName = (filePath) => {
  if (!filePath) return '';
  const parts = filePath.split(/[\/\\]/);
  return parts[parts.length - 1];
};

// 根据文件名获取语言
const getLanguage = (filename) => {
  if (!filename) return 'javascript';

  const ext = filename.split('.').pop().toLowerCase();

  const languageMap = {
    'js': 'JavaScript',
    'jsx': 'JSX',
    'ts': 'TypeScript',
    'tsx': 'TSX',
    'vue': 'Vue',
    'html': 'HTML',
    'css': 'CSS',
    'scss': 'SCSS',
    'less': 'Less',
    'json': 'JSON',
    'md': 'Markdown',
    'py': 'Python',
    'java': 'Java',
    'php': 'PHP',
    'go': 'Go',
    'rb': 'Ruby',
    'sh': 'Shell'
  };

  return languageMap[ext] || ext.toUpperCase();
};

// 代码高亮
const highlightCode = (code, filename) => {
  if (!code) return '';

  let language = '';
  if (filename) {
    const ext = filename.split('.').pop().toLowerCase();
    language = getHighlightLanguage(ext);
  }

  try {
    if (language && hljs.getLanguage(language)) {
      return hljs.highlight(code, { language }).value;
    } else {
      return hljs.highlightAuto(code).value;
    }
  } catch (error) {
    console.error('代码高亮错误:', error);
    return code;
  }
};

// 获取高亮语言
const getHighlightLanguage = (ext) => {
  const langMap = {
    'js': 'javascript',
    'jsx': 'jsx',
    'ts': 'typescript',
    'tsx': 'tsx',
    'vue': 'html', // Vue会被当作HTML处理
    'html': 'html',
    'css': 'css',
    'scss': 'scss',
    'less': 'less',
    'json': 'json',
    'md': 'markdown',
    'py': 'python',
    'java': 'java',
    'php': 'php',
    'go': 'go',
    'rb': 'ruby',
    'sh': 'bash'
  };

  return langMap[ext] || '';
};

// 高亮的代码
const highlightedCode = computed(() => {
  if (!currentFile.value) return '';
  return highlightCode(currentFile.value.content, currentFile.value.name);
});

// 高亮的全屏代码
const highlightedFullscreenCode = computed(() => {
  if (!fullscreenFile.value) return '';
  return highlightCode(fullscreenFile.value.content, fullscreenFile.value.name);
});

// 是否为小屏幕
const isSmallScreen = computed(() => {
  return window.innerWidth < 768;
});

// 复制代码
const copyCode = async () => {
  try {
    await navigator.clipboard.writeText(codeContent.value);
    showCopyNotification.value = true;

    setTimeout(() => {
      showCopyNotification.value = false;
    }, 2000);
  } catch (error) {
    console.error('复制失败:', error);
    // 可以添加失败提示
  }
};
watch(showCopyNotification, () => {
  if (showCopyNotification.value) {
    ElMessage({
      message: 'Congrats, this is a success message.',
      type: 'success',
    })
  }
})

// 复制当前文件代码
const copyCurrentCode = async () => {
  if (!fullscreenFile.value) return;

  try {
    await navigator.clipboard.writeText(fullscreenFile.value.content);
    showCopyNotification.value = true;

    setTimeout(() => {
      showCopyNotification.value = false;
    }, 2000);
  } catch (error) {
    console.error('复制失败:', error);
  }
};
</script>

<style>
.code-dialog .el-dialog__header {
  padding: 16px 20px;
  margin-right: 0;
  border-bottom: 1px solid #ebeef5;
}

.code-dialog .el-dialog__body {
  padding: 0;
}

.hljs {
  background: #282c34 !important;
  color: #abb2bf !important;
}
</style>

<style scoped>
.code-display {
  margin: 20px 0;
  padding: 0;
  background-color: #fff;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
  transition: box-shadow 0.3s ease;
}

.code-display:hover {
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);
}

.code-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  background-color: #f8fafc;
  border-bottom: 1px solid #ebeef5;
}

.header-title {
  display: flex;
  align-items: center;
}

.header-icon {
  font-size: 22px;
  margin-right: 10px;
  color: #409eff;
}

.code-header h3 {
  margin: 0;
  font-size: 18px;
  color: #303133;
  font-weight: 600;
}

.actions {
  display: flex;
  gap: 10px;
}

.action-button {
  display: flex;
  align-items: center;
  gap: 6px;
}

.code-content {
  padding: 0;
}

.code-block {
  overflow: hidden;
  display: flex;
  flex-direction: column;
  max-height: 1100px;
}

.tabs-wrapper {
  background-color: #f8fafc;
  border-bottom: 1px solid #ebeef5;
}

.file-tabs {
  display: flex;
  overflow-x: auto;
  padding: 0 20px;
  gap: 2px;
}

.file-tab {
  display: flex;
  align-items: center;
  padding: 10px 16px;
  font-size: 14px;
  cursor: pointer;
  gap: 6px;
  color: #606266;
  border-bottom: 2px solid transparent;
  transition: all 0.2s ease;
}

.file-tab:hover {
  color: #409eff;
  background-color: rgba(64, 158, 255, 0.05);
}

.file-tab.active {
  color: #409eff;
  border-bottom-color: #409eff;
  background-color: rgba(64, 158, 255, 0.1);
}

.file-name {
  white-space: nowrap;
}

.code-content-wrapper {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.file-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 16px;
  background-color: #f8fafc;
  border-bottom: 1px solid #ebeef5;
  font-size: 13px;
  color: #606266;
}

.file-path {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.language-tag {
  margin-left: 8px;
}

.code-area {
  flex: 1;
  overflow: auto;
  background-color: #f3f3f3;
}

.code-area pre {
  margin: 0;
  padding: 16px;
}

.code-area code {
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
  white-space: pre;
  word-break: normal;
  overflow-wrap: normal;
  display: block;
}

.fullscreen-code {
  display: flex;
  flex-direction: column;
  height: 80vh;
}

.actions-bar {
  display: flex;
  justify-content: space-between;
  padding: 12px 20px;
  background-color: #f8fafc;
  border-bottom: 1px solid #ebeef5;
}

.file-selection {
  max-width: 50%;
}

.file-select {
  width: 300px;
}

.copy-button {
  display: flex;
  align-items: center;
  gap: 6px;
}

.code-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.code-area.fullscreen {
  min-height: 400px;
}
</style>